package com.tzt.common;

import com.tzt.contents.CacheKeyConstant;
import com.tzt.contents.Constantpool;
import com.tzt.dao.MothodModuleMapper;
import com.tzt.entity.MothodModuleEntity;
import com.tzt.util.GetCacheUtil;
import com.tzt.util.NomalUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class WebLogAspect
{
    /**
     * 不需要打印日志的方法
     */
    private static List<String> notLogger;

    static {
        notLogger = new ArrayList<String>();
        notLogger.add("addPooboName");
        notLogger.add("updatePooboName");
    }

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    ThreadLocal<Long> startTime = new ThreadLocal<Long>();

    @Autowired
    private GetCacheUtil getCacheUtil;

    @Resource
    private MothodModuleMapper mothodModuleMapper;

    /**
     * 定义一个切入点. 解释下：
     *
     * ~ 第一个 * 代表任意修饰符及任意返回值. ~ 第二个 * 任意包名 ~ 第三个 * 代表任意方法. ~ 第四个 * 定义在web包或者子包 ~
     * 第五个 * 任意方法 ~ .. 匹配任意数量的参数.
     */
    @Pointcut("execution(* com.tzt.controller..*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void webLog(){}

    // @Before("webLog()")
    @Around("webLog()")
    public Object doBefore(ProceedingJoinPoint joinPoint) throws Throwable
    {
        startTime.set(System.currentTimeMillis());
        // 接收到请求，记录请求内容
        logger.info("WebLogAspect.doBefore()");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        String url = request.getRequestURL().toString();

        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        String methodName = joinPoint.getSignature().getName();
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."
                + methodName);
        // 获取所有参数方法一：
        Enumeration<String> enu = request.getParameterNames();
        StringBuffer sb = new StringBuffer();

        sb.append("入参：[");
        String loginRoleId = "";
        while (enu.hasMoreElements())
        {
            String paraName = (String) enu.nextElement();
            sb.append(paraName + ":" + request.getParameter(paraName)).append(" | ");
            if ("loginRoleId".equals(paraName))
            {
                loginRoleId = request.getParameter(paraName);
            }
        }
        sb.append("]");
        if(!notLogger.contains(methodName)){
            logger.info(sb.toString());
        }
        if(url.contains("MP_verify_")){
            String MP_verify_ = url.substring(url.indexOf("MP_verify_"));
            logger.info("包含" + MP_verify_);
            request.setAttribute("MP_verify_", MP_verify_);
            return joinPoint.proceed();
        }
        if(!url.contains("api/")){
            return joinPoint.proceed();
        }
        String control = url.substring(url.indexOf("api/"));
        String sysAdminRoleId = getCacheUtil.getDictValueByKey(Constantpool.DICT_ADMIN_ROLE_ID);
        if(!sysAdminRoleId.equals(loginRoleId)){
            String status = getCacheUtil.getStringRedisVal(CacheKeyConstant.SHOP_CONTROL_STATUS + control);
            if(NomalUtil.isNull(status)){
                status = mothodModuleMapper.getMethodModuleByClass(classMethod);
                if(NomalUtil.isNull(status)){
                    return joinPoint.proceed();
                }
                getCacheUtil.setStringRedisVal(CacheKeyConstant.SHOP_CONTROL_STATUS + control, status, 1,TimeUnit.HOURS);
            }
            if("1".equals(status)){
                Map<String, Object> qryMap = new HashMap<String, Object>();
                qryMap.put("loginRoleId", loginRoleId);
                qryMap.put("control", control);
                int moduleCount = mothodModuleMapper.moduleCount(qryMap);
                if (moduleCount >= 1)
                {
                    return joinPoint.proceed();
                }
                else
                {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("code", "1");
                    map.put("msg", "权限不足");
                    map.put("data", null);
                    return map;
                }
            }
        }
        return joinPoint.proceed();

    }

    // @AfterReturning("webLog()")
    @AfterReturning(value = "webLog()", argNames = "rtv", returning = "rtv")
    public void doAfterReturning(JoinPoint joinPoint, Object rvt)
    {
        // 处理完请求，返回内容
        logger.info("WebLogAspect.doAfterReturning()");
        logger.info("出参：" + rvt);
        logger.info("耗时（毫秒） : " + (System.currentTimeMillis() - startTime.get()));
    }

}
